/**
 * 
 */
package jvs.core.http;


import java.io.IOException;
import java.net.BindException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.URL;
import java.util.Properties;

import jvs.core.Lifecycle;


/**
 * @author qiangli
 * 
 */
public class HttpConnector implements Connector, Lifecycle, Runnable {
	private static final String PROTOCOL = "http";

	private int instanceId = 0;

	private String host = "localhost";

	private int port = 80; 

	private PI pi;

	private ServerSocket ss;

	private Thread th;

	/** 
	 */
	public HttpConnector() {
	}

	public void setPI(PI pi) {
		this.pi = pi;
	}

	public void init(Properties attrs) {
		try {
			this.host = attrs.getProperty("http.host", "localhost");
			this.port = Integer.parseInt(attrs.getProperty("http.port","80"));
		} catch (Exception e) {
			//e.printStackTrace();
		}
	}

	public void run() {
		while (ss != null) {
			try {
				log("HTTP Connector [" + host + ":" + port + " "
						+ (++instanceId) + "]");
				Socket s = ss.accept();
				if (pi != null) {
					Context ctx = new Context(PROTOCOL);
					ctx.setLocal(false);
					ctx.baseUri = new URL("http",host,port,"/").toURI();

					InetSocketAddress la = (InetSocketAddress) s
							.getLocalSocketAddress();

					ctx.setLocalHost(la.getHostName());
					ctx.setLocalPort(la.getPort());

					InetSocketAddress ra = (InetSocketAddress) s
							.getRemoteSocketAddress();

					ctx.setRemoteHost(ra.getHostName());
					ctx.setRemotePort(ra.getPort());

					pi.service(ctx, s);
				} else {
					log("No PI set.");
				}
			} catch (Exception e) {
				//e.printStackTrace();
			}
		}
	}

	private void log(String s) {
		System.out.println(s);
	}

	public void shutdown() {
		try {
			ss.close();
			ss = null;
		} catch (IOException e) {
			e.printStackTrace();
		}
		//
		th.interrupt();
	}

	public void startup() {
		while (true) {
			try {
				InetSocketAddress ep = new InetSocketAddress(host, port);
				ss = new ServerSocket();
				ss.bind(ep);
				
				break;
			} catch (BindException e) {
				e.printStackTrace();
				port++;
				continue;
				// return;
			} catch (Exception e) {
				e.printStackTrace();
				return;
			}
		}
		//
		th = new Thread(this);
		th.start();
	}
}
